
 
package com.junitUtil.spring;	
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import com.junitUtil.util.Loader;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperFactoryBean;



/**
 * TODO(描述这个类的作用) 
 * 
 **/

public class BeanCreatUtils {
    public static <T>T getBean(Class<T> cls,AbstractAutowireCapableBeanFactory beanFactory,boolean isQuick) throws Exception{
        Object obj=null;
		try {
			obj = beanFactory.getBean(cls);
		} catch (Exception e) {
 		}
        if(obj!=null){
            return (T) obj;
        }
        if (cls.isInterface() && cls.getName().contains("Mapper")) {
            MapperFactoryBean bean = registMapper(cls ,beanFactory);
            return (T) bean.getObject();
        }else   if (cls.isInterface()) {
        	 

                Class t = getImplClass(cls);
                if (isQuick) {
                    setMapper(t,beanFactory);
                }
                 obj = beanFactory.createBean(t, 2, false);
        	
        	
        } else {
            if (isQuick) {
                setMapper(cls,beanFactory);
            } 
            obj = beanFactory.createBean(cls, 2, false);
        }
        //加这个代码是之前那个地方实例化后的代理导致后续代码执行失败，后来找不到具体场景了
        //但是又发现加上会导致代理没了，导致后续spring事务处理失效
//          obj = AopTargetUtils.getTarget(obj);
        beanFactory.registerSingleton(cls.getName(), obj);
        beanFactory.autowireBean(obj);
        return (T) obj;
    }
    /**
     * @param obj
     * @author huanglinlong
     * @throws Exception
     * @date 2018年8月24日 下午4:33:16
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected static void setMapper(Class  obj,AbstractAutowireCapableBeanFactory beanFactory) throws Exception {
        for (Field field : obj.getDeclaredFields()) {
            if (!field.getType().isInterface()) {
                continue;
            }
            if (!field.getType().getName().contains("Mapper")) {
                continue;
            }
            for(Class clz:field.getType().getInterfaces()){
                   registMapper(clz,beanFactory);

            }
            registMapper(field.getType() ,beanFactory );
         
        }
    }
    @SuppressWarnings({ "rawtypes", "unchecked", "unused" })
    protected static MapperFactoryBean  registMapper(Class clz ,AbstractAutowireCapableBeanFactory beanFactory) throws   Exception {

        MapperFactoryBean bean = new    MapperFactoryBean   ( );
        bean.setSqlSessionFactory(beanFactory.getBean(SqlSessionFactoryBean.class).getObject());
        bean.setMapperInterface(clz);
        bean.setAddToConfig(true);
        org.apache.ibatis.session.Configuration configuration=bean.getSqlSession().getConfiguration();
        if(!configuration.hasMapper(clz)){
            configuration.addMapper(clz);
            beanFactory.registerSingleton(clz.getName(), bean);
            //取别名，解决Mapper和subMapper同时出现在同一个bean中需要注入的场景
            String mapperName=clz.getName().substring(clz.getName().lastIndexOf(".")+1);
            beanFactory.registerAlias(clz.getName(),StringUtils.uncapitalize(mapperName));
        } 
        return bean;
    }
    
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Class getImplClass(Class target) throws Exception {

        String root = target.getPackage().getName().replace(".", "/");
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> enumeration = classLoader.getResources(root);
        List<Class> list = new ArrayList<Class>();
        while (enumeration.hasMoreElements()) {
            URL url = enumeration.nextElement();        
            list.addAll(getClass(root, new File(url.getFile())));
        }
        for (Class cls : list) {
            if (!target.equals(cls)&&target.isAssignableFrom(cls)) {
                return cls;
            }
        }
        return null;
    }

    @SuppressWarnings({ "rawtypes", "unused" })
    protected static List<Class> getClass(String root, File baseFile) throws Exception {
        List<Class> list = new ArrayList<Class>();
        for (File file : baseFile.listFiles()) {
           String fileBase=file.getCanonicalPath().replace("\\", "/");
           if(!fileBase.contains(root)){
               continue; 
           }
            if (file.isDirectory()) {
                list.addAll(getClass(root, file));
            } else {
             
                String root1=fileBase.split(root)[0].replace("/", "\\");
                String subPath =fileBase.split(root)[1];
                subPath = subPath.split("\\.")[0];
                subPath = root + subPath;
                subPath = subPath.replace("/", ".");
                 
                
                 try {
                      Class cls = loadClassFromFile(root1,subPath );
 
                    list.add(cls);
                } catch (Exception e) {
                    e.printStackTrace( );
                }
                
            }
        }
        return list;
    }
    protected static Class loadClassFromFile(String classPath,String className) throws Exception{
        ClassLoader loader=new Loader(classPath);
        return loader.loadClass(className);
    }
	 
}

